package com.sun.tools.xjc.addons.android_plugin;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.sun.codemodel.JAnnotationUse;
import com.sun.codemodel.JAnnotationValue;
import com.sun.codemodel.JDefinedClass;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JStringLiteral;
import com.sun.codemodel.JType;

public class APXmlElement {
  public String variableName;
  public ArrayList<String> names;
  public ArrayList<JType> types;
  public ArrayList<String> namespaces;
  public JFieldVar field;
  
  // TODO: defaultvalue, nillable, required
  
  public APXmlElement() {
    variableName = "";
    names = new ArrayList<>();
    types = new ArrayList<>();
    namespaces = new ArrayList<>();
    field = null;
  }

  public APXmlElement(JAnnotationUse xmlAnnotation, String name, JFieldVar field) throws Exception 
  {
    variableName = name;
    names = new ArrayList<>();
    types = new ArrayList<>();
    namespaces = new ArrayList<>();
    this.field = field;

    String annotationName = xmlAnnotation.getAnnotationClass().name();

    if(annotationName.equals("XmlElement") || annotationName.equals("XmlElementRef")) {
      Object[] info =
          getNameTypeAndNamespaceFromXmlElementAnnotation(xmlAnnotation);
      this.names.add((String)info[0]);
      this.types.add((JType) info[1]);
      this.namespaces.add((String)info[2]);
    } else if (annotationName.equals("XmlElements") || annotationName.equals("XmlElementRefs")) {
      List<Object[]> infos = 
          getNamesTypesAndNamespacesFromXmlElementsAnnotation(xmlAnnotation);

      for(Object[] info : infos) {
        this.names.add((String)info[0]);
        this.types.add((JType) info[1]);
        this.namespaces.add((String)info[2]);
      }
    } else {
      throw new Exception("The given annotation was not of type XmlElement or XmlElements");
    }
  }
  

  private static List<Object[]> getNamesTypesAndNamespacesFromXmlElementsAnnotation(
      JAnnotationUse xmlElementsAttribute) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
    List<Object[]> info = new ArrayList<Object[]>();
    Map<String, JAnnotationValue> memberMap = 
        xmlElementsAttribute.getAnnotationMembers();
    JAnnotationValue valueMember = memberMap.get("value");
    ArrayList<JAnnotationUse> valueMemberValues = Utilities.getFieldValue(valueMember, "values");
    
    for(JAnnotationUse subElement : valueMemberValues) {
      String subElementName = subElement.getAnnotationClass().name();
      
      if(subElementName.equals("XmlElement") || subElementName.equals("XmlElementRef")) {
        Object[] objs = getNameTypeAndNamespaceFromXmlElementAnnotation(subElement);
        info.add(objs);
      }
    }
    
    return info;
  }
  
  private static Object[] getNameTypeAndNamespaceFromXmlElementAnnotation(
      JAnnotationUse xmlElementAnnotation) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
    Object[] objs = new Object[3];
    
    Map<String, JAnnotationValue> memberMap = xmlElementAnnotation.getAnnotationMembers();
    
    if(memberMap.containsKey("name")) {
      JAnnotationValue val = memberMap.get("name");
      JStringLiteral jval = Utilities.getFieldValue(val, "value");
      objs[0] = jval.str;
    } else {
      objs[0] = null;
    }
    
    if(memberMap.containsKey("type")) {
      JAnnotationValue val = memberMap.get("type");
      Object innerValue = Utilities.getFieldValue(val, "value");
      JType innerInnverValue = Utilities.getFieldValue(innerValue, "val$cl");
      objs[1] = innerInnverValue;
    } else {
      objs[1] = null;
    }
    
    if(memberMap.containsKey("namespace")) {
      JAnnotationValue val = memberMap.get("namespace");
      JStringLiteral jval = Utilities.getFieldValue(val, "value");
      objs[2] = jval.str;
    } else {
      objs[2] = null;
    }
    
    return objs;
  }
  
}
